home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / psi110g.zip / IPROUTE.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  31KB  |  967 lines

  1. /* Lower half of IP, consisting of gateway routines
  2.  * Includes routing and options processing code
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Mods by PA0GRI
  7.  */
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "socket.h"
  11. #include "iface.h"
  12. #include "timer.h"
  13. #include "internet.h"
  14. #include "ip.h"
  15. #include "netuser.h"
  16. #include "icmp.h"
  17. #include "rip.h"
  18. #include "trace.h"
  19. #include "pktdrvr.h"
  20. #include "bootp.h"
  21.   
  22.   
  23. struct route *Routes[32][HASHMOD];  /* Routing table */
  24. struct route R_default = {      /* Default route entry */
  25.     NULLROUTE, NULLROUTE,
  26.     0,0,0,
  27.     RIP_INFINITY        /* Init metric to infinity */
  28. };
  29.   
  30. static struct rt_cache Rt_cache;
  31.   
  32. #ifdef IPACCESS
  33. #define NETBITS(bits) ((bits) == 0 ? 0 : (~0L << (32 - bits)))
  34. struct rtaccess *IPaccess = NULLACCESS; /* access list */
  35. #endif
  36.   
  37. /* Initialize modulo lookup table used by hash_ip() in pcgen.asm */
  38. void
  39. ipinit()
  40. {
  41.     int i;
  42.   
  43.     for(i=0;i<256;i++)
  44.         Hashtab[i] = i % HASHMOD;
  45. }
  46.   
  47. /* Route an IP datagram. This is the "hopper" through which all IP datagrams,
  48.  * coming or going, must pass.
  49.  *
  50.  * "rxbroadcast" is set to indicate that the packet came in on a subnet
  51.  * broadcast. The router will kick the packet upstairs regardless of the
  52.  * IP destination address.
  53.  */
  54.   
  55. int
  56. ip_route(i_iface,bp,rxbroadcast)
  57. struct iface *i_iface;  /* Input interface */
  58. struct mbuf *bp;    /* Input packet */
  59. int rxbroadcast;    /* True if packet had link broadcast address */
  60. {
  61.     struct ip ip;           /* IP header being processed */
  62.     int16 ip_len;           /* IP header length */
  63.     int16 length;           /* Length of data portion */
  64.     int32 gateway;          /* Gateway IP address */
  65.     register struct route *rp;  /* Route table entry */
  66.     struct iface *iface;        /* Output interface, possibly forwarded */
  67.     int16 offset;           /* Offset into current fragment */
  68.     int16 mf_flag;          /* Original datagram MF flag */
  69.     int strict = 0;         /* Strict source routing flag */
  70.     char prec;          /* Extracted from tos field */
  71.     char del;
  72.     char tput;
  73.     char rel;
  74.     int16 opt_len;      /* Length of current option */
  75.     char *opt;      /* -> beginning of current option */
  76.     int i;
  77.     struct mbuf *tbp;
  78.     int ckgood = IP_CS_OLD; /* Has good checksum without modification */
  79. #ifdef IPACCESS
  80.     int16 srcport, dstport; /* for use in access checking */
  81.     struct rtaccess *tpacc; /* temporary for access checking */
  82. #endif
  83.     int pointer;        /* Relative pointer index for sroute/rroute */
  84.   
  85.     if(i_iface != NULLIF){
  86.         ipInReceives++; /* Not locally generated */
  87.         i_iface->iprecvcnt++;
  88.     }
  89.   
  90.     if(len_p(bp) < IPLEN){
  91.         /* The packet is shorter than a legal IP header */
  92.         ipInHdrErrors++;
  93.         free_p(bp);
  94.         return -1;
  95.     }
  96.     /* Sneak a peek at the IP header's IHL field to find its length */
  97.     ip_len = (bp->data[0] & 0xf) << 2;
  98.     if(ip_len < IPLEN){
  99.         /* The IP header length field is too small */
  100.         ipInHdrErrors++;
  101.         free_p(bp);
  102.         return -1;
  103.     }
  104.     if(cksum(NULLHEADER,bp,ip_len) != 0){
  105.         /* Bad IP header checksum; discard */
  106.         ipInHdrErrors++;
  107.         free_p(bp);
  108.         return -1;
  109.     }
  110.     /* Extract IP header */
  111.     ntohip(&ip,&bp);
  112.   
  113.     if(ip.version != IPVERSION){
  114.         /* We can't handle this version of IP */
  115.         ipInHdrErrors++;
  116.         free_p(bp);
  117.         return -1;
  118.     }
  119.   
  120.     /* IP logging added - WG7J
  121.      * only if not an AX.25 interface, since those are already
  122.      * logged in ax_recv() in ax25.c
  123.      */
  124.     if((i_iface != NULLIF) && (i_iface->type != CL_AX25) &&
  125.         (i_iface->flags & LOG_IPHEARD) )
  126.         log_ipheard(ip.source,i_iface);
  127.   
  128.     /* Trim data segment if necessary. */
  129.     length = ip.length - ip_len;    /* Length of data portion */
  130.     trim_mbuf(&bp,length);
  131.   
  132.     /* If we're running low on memory, return a source quench */
  133.     if(!rxbroadcast && availmem() < Memthresh) {
  134.         extern int Icmp_SQ;
  135.         /* If we don't allow source quenches to be sent,
  136.          * drop the packet - WG7J
  137.          */
  138.         if(!Icmp_SQ) {
  139.             free_p(bp);
  140.             return -1;
  141.         }
  142.         icmp_output(&ip,bp,ICMP_QUENCH,0,NULLICMP);
  143.     }
  144.   
  145.     /* Process options, if any. Also compute length of secondary IP
  146.      * header in case fragmentation is needed later
  147.      */
  148.     strict = 0;
  149.     for(i=0;i<ip.optlen;i += opt_len){
  150.   
  151.         /* First check for the two special 1-byte options */
  152.         switch(ip.options[i] & OPT_NUMBER){
  153.             case IP_EOL:
  154.                 goto no_opt;    /* End of options list, we're done */
  155.             case IP_NOOP:
  156.                 opt_len = 1;
  157.                 continue;   /* No operation, skip to next option */
  158.         }
  159.         /* Not a 1-byte option, so ensure that there's at least
  160.          * two bytes of option left, that the option length is
  161.          * at least two, and that there's enough space left for
  162.          * the specified option length.
  163.          */
  164.         if(ip.optlen - i < 2
  165.             || ((opt_len = uchar(ip.options[i+1])) < 2)
  166.         || ip.optlen - i < opt_len){
  167.             /* Truncated option, send ICMP and drop packet */
  168.             if(!rxbroadcast){
  169.                 union icmp_args icmp_args;
  170.   
  171.                 icmp_args.pointer = IPLEN + i;
  172.                 icmp_output(&ip,bp,ICMP_PARAM_PROB,0,&icmp_args);
  173.             }
  174.             free_p(bp);
  175.             return -1;
  176.         }
  177.         opt = &ip.options[i];
  178.   
  179.         switch(opt[0] & OPT_NUMBER){
  180.             case IP_SSROUTE:    /* Strict source route & record route */
  181.                 strict = 1; /* note fall-thru */
  182.             case IP_LSROUTE:    /* Loose source route & record route */
  183.             /* Source routes are ignored unless we're in the
  184.              * destination field
  185.              */
  186.                 if(opt_len < 3){
  187.                 /* Option is too short to be a legal sroute.
  188.                  * Send an ICMP message and drop it.
  189.                  */
  190.                     if(!rxbroadcast){
  191.                         union icmp_args icmp_args;
  192.   
  193.                         icmp_args.pointer = IPLEN + i;
  194.                         icmp_output(&ip,bp,ICMP_PARAM_PROB,0,&icmp_args);
  195.                     }
  196.                     free_p(bp);
  197.                     return -1;
  198.                 }
  199.                 if(ismyaddr(ip.dest) == NULLIF)
  200.                     break;  /* Skip to next option */
  201.                 pointer = uchar(opt[2]);
  202.                 if(pointer + 4 > opt_len)
  203.                     break;  /* Route exhausted; it's for us */
  204.   
  205.             /* Put address for next hop into destination field,
  206.              * put our address into the route field, and bump
  207.              * the pointer. We've already ensured enough space.
  208.              */
  209.                 ip.dest = get32(&opt[pointer]);
  210.                 put32(&opt[pointer],locaddr(ip.dest));
  211.                 opt[2] += 4;
  212.                 ckgood = IP_CS_NEW;
  213.                 break;
  214.             case IP_RROUTE: /* Record route */
  215.                 if(opt_len < 3){
  216.                 /* Option is too short to be a legal rroute.
  217.                  * Send an ICMP message and drop it.
  218.                  */
  219.                     if(!rxbroadcast){
  220.                         union icmp_args icmp_args;
  221.   
  222.                         icmp_args.pointer = IPLEN + i;
  223.                         icmp_output(&ip,bp,ICMP_PARAM_PROB,0,&icmp_args);
  224.                     }
  225.                     free_p(bp);
  226.                     return -1;
  227.                 }
  228.                 pointer = uchar(opt[2]);
  229.                 if(pointer + 4 > opt_len){
  230.                 /* Route area exhausted; send an ICMP msg */
  231.                     if(!rxbroadcast){
  232.                         union icmp_args icmp_args;
  233.   
  234.                         icmp_args.pointer = IPLEN + i;
  235.                         icmp_output(&ip,bp,ICMP_PARAM_PROB,0,&icmp_args);
  236.                     }
  237.                 /* Also drop if odd-sized */
  238.                     if(pointer != opt_len){
  239.                         free_p(bp);
  240.                         return -1;
  241.                     }
  242.                 } else {
  243.                 /* Add our address to the route.
  244.                  * We've already ensured there's enough space.
  245.                  */
  246.                     put32(&opt[pointer],locaddr(ip.dest));
  247.                     opt[2] += 4;
  248.                     ckgood = IP_CS_NEW;
  249.                 }
  250.                 break;
  251.         }
  252.     }
  253.     no_opt:
  254.   
  255.     /* See if it's a broadcast or addressed to us, and kick it upstairs */
  256.     if(ismyaddr(ip.dest) != NULLIF || rxbroadcast ||
  257.     (WantBootp && bootp_validPacket(&ip, &bp))){
  258. #ifdef  GWONLY
  259.     /* We're only a gateway, we have no host level protocols */
  260.         if(!rxbroadcast)
  261.             icmp_output(&ip,bp,ICMP_DEST_UNREACH,
  262.             ICMP_PROT_UNREACH,NULLICMP);
  263.         ipInUnknownProtos++;
  264.         free_p(bp);
  265. #else
  266.         ip_recv(i_iface,&ip,bp,rxbroadcast);
  267. #endif  /*GWONLY */
  268.         return 0;
  269.     }
  270.   
  271.     /* Packet is not destined to us. If it originated elsewhere, count
  272.      * it as a forwarded datagram.
  273.      */
  274.     if(i_iface != NULLIF)
  275.         ipForwDatagrams++;
  276.   
  277.     /* Adjust the header checksum to allow for the modified TTL */
  278.     ip.checksum += 0x100;
  279.     if((ip.checksum & 0xff00) == 0)
  280.         ip.checksum++;  /* end-around carry */
  281.   
  282.     /* Decrement TTL and discard if zero. We don't have to check
  283.      * rxbroadcast here because it's already been checked
  284.      */
  285.     if(--ip.ttl == 0){
  286.         /* Send ICMP "Time Exceeded" message */
  287.         /* If the following flag is not set, we don't send this !
  288.          * This makes our system 'invisible' for traceroutes,
  289.          * and might be a little more secure for internet<->ampr
  290.          * gateways - WG7J
  291.          */
  292.         extern int Icmp_timeexceed;
  293.   
  294.         if(Icmp_timeexceed)
  295.             icmp_output(&ip,bp,ICMP_TIME_EXCEED,0,NULLICMP);
  296.         ipInHdrErrors++;
  297.         free_p(bp);
  298.         return -1;
  299.     }
  300.     /* Look up target address in routing table */
  301.     if((rp = rt_lookup(ip.dest)) == NULLROUTE){
  302.         /* No route exists, return unreachable message (we already
  303.          * know this can't be a broadcast)
  304.          */
  305.         icmp_output(&ip,bp,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,NULLICMP);
  306.         free_p(bp);
  307.         ipOutNoRoutes++;
  308.         return -1;
  309.     }
  310.     rp->uses++;
  311.   
  312.     /* Check for output forwarding and divert if necessary */
  313.     iface = rp->iface;
  314.     if(iface->forw != NULLIF)
  315.         iface = iface->forw;
  316.   
  317. #ifdef IPACCESS
  318. /* At this point we've decided to send the packet out 'iface' (unless it
  319. won't fragment).  Check ip.protocol for tcp or udp.
  320. Should probably have counter on number of dropped packets.
  321. */
  322.     if((ip.protocol == TCP_PTCL) || (ip.protocol==UDP_PTCL)) {
  323.         /* pull up source & destination port */
  324.         srcport = get16(&(bp->data[0])); /*done for futures & debug*/
  325.         dstport = get16(&(bp->data[2]));
  326.     }
  327.     /* for backwards compatibility, if there are *no* entries */
  328.     /* we ignore access control, so everything is legal. Any  */
  329.     /* entry for an iface means default is to drop if no      */
  330.     /* permission found  */
  331.     for( tpacc = IPaccess;tpacc != NULLACCESS;tpacc=tpacc->nxtiface) {
  332.         /*find a matching iface*/
  333.         if(tpacc->iface == iface ){ /* Needs to be authorized */
  334.             if(!ip_check(tpacc, ip.protocol, ip.source, ip.dest, dstport))
  335.                 break;
  336.             /* not found, throw it away. */
  337.             /* if NO access, then drop & increment counter */
  338.             /* see new(er) RFC for proper ICMP codes */
  339.             /* maybe counter is in MIB? else create.*/
  340.             icmp_output(&ip,bp,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,NULLICMP);
  341.             ipOutNoRoutes++;
  342.             free_p(bp);
  343.             return -1;
  344.         }
  345.     }
  346. #endif
  347.     /* Find gateway; zero gateway in routing table means "send direct" */
  348.     if(rp->gateway == 0)
  349.         gateway = ip.dest;
  350.     else
  351.         gateway = rp->gateway;
  352.   
  353.     if(strict && gateway != ip.dest){
  354.         /* Strict source routing requires a direct entry
  355.          * Again, we know this isn't a broadcast
  356.          */
  357.         icmp_output(&ip,bp,ICMP_DEST_UNREACH,ICMP_ROUTE_FAIL,NULLICMP);
  358.         free_p(bp);
  359.         ipOutNoRoutes++;
  360.         return -1;
  361.     }
  362.     prec = PREC(ip.tos);
  363.     del = ip.tos & DELAY;
  364.     tput = ip.tos & THRUPUT;
  365.     rel = ip.tos & RELIABILITY;
  366.   
  367.     if(ip.length <= iface->mtu){
  368.         /* Datagram smaller than interface MTU; put header
  369.          * back on and send normally.
  370.          */
  371.         if((tbp = htonip(&ip,bp,ckgood)) == NULLBUF){
  372.             free_p(bp);
  373.             return -1;
  374.         }
  375.         iface->ipsndcnt++;
  376.         return (*iface->send)(tbp,iface,gateway,prec,del,tput,rel);
  377.     }
  378.     /* Fragmentation needed */
  379.     if(ip.flags.df){
  380.         /* Don't Fragment set; return ICMP message and drop */
  381.         union icmp_args icmp_args;
  382.   
  383.         icmp_args.mtu = iface->mtu;
  384.         icmp_output(&ip,bp,ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED,&icmp_args);
  385.         free_p(bp);
  386.         ipFragFails++;
  387.         return -1;
  388.     }
  389.     /* Create fragments */
  390.     offset = ip.offset;
  391.     mf_flag = ip.flags.mf;      /* Save original MF flag */
  392.     while(length != 0){     /* As long as there's data left */
  393.         int16 fragsize;     /* Size of this fragment's data */
  394.         struct mbuf *f_data;    /* Data portion of fragment */
  395.   
  396.         /* After the first fragment, should remove those
  397.          * options that aren't supposed to be copied on fragmentation
  398.          */
  399.         ip.offset = offset;
  400.         if(length + ip_len <= iface->mtu){
  401.             /* Last fragment; send all that remains */
  402.             fragsize = length;
  403.             ip.flags.mf = mf_flag;  /* Pass original MF flag */
  404.         } else {
  405.             /* More to come, so send multiple of 8 bytes */
  406.             fragsize = (iface->mtu - ip_len) & 0xfff8;
  407.             ip.flags.mf = 1;
  408.         }
  409.         ip.length = fragsize + ip_len;
  410.   
  411.         /* Duplicate the fragment */
  412.         dup_p(&f_data,bp,offset,fragsize);
  413.         if(f_data == NULLBUF){
  414.             free_p(bp);
  415.             ipFragFails++;
  416.             return -1;
  417.         }
  418.         /* Put IP header back on, recomputing checksum */
  419.         if((tbp = htonip(&ip,f_data,IP_CS_NEW)) == NULLBUF){
  420.             free_p(f_data);
  421.             free_p(bp);
  422.             ipFragFails++;
  423.             return -1;
  424.         }
  425.         /* and ship it out */
  426.         if((*iface->send)(tbp,iface,gateway,prec,del,tput,rel) == -1){
  427.             ipFragFails++;
  428.             free_p(bp);
  429.             return -1;
  430.         }
  431.         iface->ipsndcnt++;
  432.         ipFragCreates++;
  433.         offset += fragsize;
  434.         length -= fragsize;
  435.     }
  436.     ipFragOKs++;
  437.     free_p(bp);
  438.     return 0;
  439. }
  440.   
  441. #ifdef ENCAP
  442. int
  443. ip_encap(bp,iface,gateway,prec,del,tput,rel)
  444. struct mbuf *bp;
  445. struct iface *iface;
  446. int32 gateway;
  447. int prec;
  448. int del;
  449. int tput;
  450. int rel;
  451. {
  452.     struct ip ip;
  453.   
  454.     dump(iface,IF_TRACE_OUT,CL_NONE,bp);
  455.     iface->rawsndcnt++;
  456.     iface->lastsent = secclock();
  457.   
  458.     if(gateway == 0L){
  459.         /* Gateway must be specified */
  460.         ntohip(&ip,&bp);
  461.         icmp_output(&ip,bp,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,NULLICMP);
  462.         free_p(bp);
  463.         ipOutNoRoutes++;
  464.         return -1;
  465.     }
  466.     return ip_send(INADDR_ANY,gateway,IP_PTCL,0,0,bp,0,0,0);
  467. }
  468. #endif /*ENCAP*/
  469.   
  470. /* Add an entry to the IP routing table. Returns 0 on success, -1 on failure */
  471. struct route *
  472. rt_add(target,bits,gateway,iface,metric,ttl,private)
  473. int32 target;       /* Target IP address prefix */
  474. unsigned int bits;  /* Size of target address prefix in bits (0-32) */
  475. int32 gateway;      /* Optional gateway to be reached via interface */
  476. struct iface *iface;    /* Interface to which packet is to be routed */
  477. int32 metric;       /* Metric for this route entry */
  478. int32 ttl;      /* Lifetime of this route entry in sec */
  479. char private;       /* Inhibit advertising this entry ? */
  480. {
  481.     struct route *rp,**hp;
  482.     struct route *rptmp;
  483.     int32 gwtmp;
  484.   
  485.     if(iface == NULLIF)
  486.         return NULLROUTE;
  487.   
  488.     if(bits == 32 && ismyaddr(target))
  489.         return NULLROUTE;   /* Don't accept routes to ourselves */
  490.   
  491.     if(bits > 32)
  492.         bits = 32;      /* Bulletproofing */
  493. #ifdef ENCAP
  494.     /* Encapsulated routes must specify gateway, and it can't be
  495.      *  ourselves
  496.      */
  497.     if(iface == &Encap && (gateway == 0 || ismyaddr(gateway)))
  498.         return NULLROUTE;
  499. #endif
  500.   
  501.     Rt_cache.route = NULLROUTE; /* Flush cache */
  502.   
  503.     /* Mask off don't-care bits of target */
  504.     target &= ~0L << (32-bits);
  505.   
  506.     /* Zero bits refers to the default route */
  507.     if(bits == 0){
  508.         rp = &R_default;
  509.     } else {
  510.         rp = rt_blookup(target,bits);
  511.     }
  512.     if(rp == NULLROUTE){
  513.         /* The target is not already in the table, so create a new
  514.          * entry and put it in.
  515.          */
  516.         rp = (struct route *)callocw(1,sizeof(struct route));
  517.         /* Insert at head of table */
  518.         rp->prev = NULLROUTE;
  519.         hp = &Routes[bits-1][hash_ip(target)];
  520.         rp->next = *hp;
  521.         if(rp->next != NULLROUTE)
  522.             rp->next->prev = rp;
  523.         *hp = rp;
  524.         rp->uses = 0;
  525.     }
  526.     rp->target = target;
  527.     rp->bits = bits;
  528.     rp->gateway = gateway;
  529.     rp->metric = metric;
  530.     rp->iface = iface;
  531.     rp->flags = private ? RTPRIVATE : 0;    /* Should anyone be told of this route? */
  532.     rp->timer.func = rt_timeout;  /* Set the timer field */
  533.     rp->timer.arg = (void *)rp;
  534.     set_timer(&rp->timer,ttl*1000L);
  535.     stop_timer(&rp->timer);
  536.     start_timer(&rp->timer); /* start the timer if appropriate */
  537.   
  538. #ifdef ENCAP
  539.     /* Check to see if this created an encapsulation loop */
  540.     gwtmp = gateway;
  541.     for(;;){
  542.         rptmp = rt_lookup(gwtmp);
  543.         if(rptmp == NULLROUTE)
  544.             break;  /* No route to gateway, so no loop */
  545.         if(rptmp->iface != &Encap)
  546.             break;  /* Non-encap interface, so no loop */
  547.         if(rptmp == rp){
  548.             rt_drop(target,bits);   /* Definite loop */
  549.             return NULLROUTE;
  550.         }
  551.         if(rptmp->gateway != 0)
  552.             gwtmp = rptmp->gateway;
  553.     }
  554. #endif
  555.     return rp;
  556. }
  557.   
  558. /* Remove an entry from the IP routing table. Returns 0 on success, -1
  559.  * if entry was not in table.
  560.  */
  561. int
  562. rt_drop(target,bits)
  563. int32 target;
  564. unsigned int bits;
  565. {
  566.     register struct route *rp;
  567.   
  568.     Rt_cache.route = NULLROUTE; /* Flush the cache */
  569.   
  570.     if(bits == 0){
  571.         /* Nail the default entry */
  572.         stop_timer(&R_default.timer);
  573.         R_default.iface = NULLIF;
  574.         return 0;
  575.     }
  576.     if(bits > 32)
  577.         bits = 32;
  578.   
  579.     /* Mask off target according to width */
  580.     target &= ~0L << (32-bits);
  581.   
  582.     /* Search appropriate chain for existing entry */
  583.     for(rp = Routes[bits-1][hash_ip(target)];rp != NULLROUTE;rp = rp->next){
  584.         if(rp->target == target)
  585.             break;
  586.     }
  587.     if(rp == NULLROUTE)
  588.         return -1;  /* Not in table */
  589.   
  590.     stop_timer(&rp->timer);
  591.     if(rp->next != NULLROUTE)
  592.         rp->next->prev = rp->prev;
  593.     if(rp->prev != NULLROUTE)
  594.         rp->prev->next = rp->next;
  595.     else
  596.         Routes[bits-1][hash_ip(target)] = rp->next;
  597.   
  598.     free((char *)rp);
  599.     return 0;
  600. }
  601. #ifdef  notdef
  602.   
  603. /* Compute hash function on IP address */
  604. static int16
  605. hash_ip(addr)
  606. register int32 addr;
  607. {
  608.     register int16 ret;
  609.   
  610.     ret = hiword(addr);
  611.     ret ^= loword(addr);
  612.     return (int16)(ret % HASHMOD);
  613. }
  614. #endif
  615. #ifndef GWONLY
  616. /* Given an IP address, return the MTU of the local interface used to
  617.  * reach that destination. This is used by TCP to avoid local fragmentation
  618.  */
  619. int16
  620. ip_mtu(addr)
  621. int32 addr;
  622. {
  623.     register struct route *rp;
  624.     struct iface *iface;
  625.   
  626.     rp = rt_lookup(addr);
  627.     if(rp == NULLROUTE || rp->iface == NULLIF)
  628.         return 0;
  629.   
  630.     iface = rp->iface;
  631.     if(iface->forw != NULLIF)
  632.         return iface->forw->mtu;
  633.     else
  634.         return iface->mtu;
  635. }
  636. /* Given a destination address, return the IP address of the local
  637.  * interface that will be used to reach it. If there is no route
  638.  * to the destination, pick the first non-loopback address.
  639.  */
  640. int32
  641. locaddr(addr)
  642. int32 addr;
  643. {
  644.     register struct route *rp;
  645.     struct iface *ifp;
  646.   
  647.     if(ismyaddr(addr) != NULLIF)
  648.         return addr;    /* Loopback case */
  649.   
  650.     rp = rt_lookup(addr);
  651.     if(rp != NULLROUTE && rp->iface != NULLIF)
  652.         ifp = rp->iface;
  653.     else {
  654.         /* No route currently exists, so just pick the first real
  655.          * interface and use its address
  656.          */
  657.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  658. #ifdef ENCAP
  659.             if(ifp != &Loopback && ifp != &Encap)
  660. #else
  661.                 if(ifp != &Loopback)
  662. #endif
  663.                     break;
  664.         }
  665.     }
  666.     if(ifp == NULLIF || ifp == &Loopback)
  667.         return 0;   /* No dice */
  668.   
  669. #ifdef ENCAP
  670.     if(ifp == &Encap){
  671.         /* Recursive call - we assume that there are no circular
  672.          * encapsulation references in the routing table!!
  673.          * (There is a check at the end of rt_add() that goes to
  674.          * great pains to ensure this.)
  675.          */
  676.         /* Next couple of lines are a point of discussion
  677.          * The ultimate source for encaptulation is the local
  678.          * IP address. Phil looks for the address of the addres
  679.          * to be used, ending up with the wrong one (in my oppinion)
  680.          * If you disagree set encap ip address to what you want.
  681.          */
  682.         if(Encap.addr != 0)
  683.             return Encap.addr;
  684. #ifdef notdef
  685.         return locaddr(rp->gateway);
  686. #else
  687.         return Ip_addr;
  688. #endif
  689.     }
  690. #endif /*ENCAP*/
  691.     if(ifp->forw != NULLIF)
  692.         return ifp->forw->addr;
  693.     else
  694.         return ifp->addr;
  695. }
  696. #endif /*GWONLY*/
  697. /* Look up target in hash table, matching the entry having the largest number
  698.  * of leading bits in common. Return default route if not found;
  699.  * if default route not set, return NULLROUTE
  700.  */
  701. struct route *
  702. rt_lookup(target)
  703. int32 target;
  704. {
  705.     register struct route *rp;
  706.     int bits;
  707.     int32 tsave;
  708.     int32 mask;
  709.   
  710.     /* Examine cache first */
  711.     if(target == Rt_cache.target && Rt_cache.route != NULLROUTE)
  712.         return Rt_cache.route;
  713.   
  714.     tsave = target;
  715.   
  716.     mask = ~0L; /* All ones */
  717.     for(bits = 31;bits >= 0; bits--){
  718.         target &= mask;
  719.         for(rp = Routes[bits][hash_ip(target)];rp != NULLROUTE;rp = rp->next){
  720.             if(rp->target == target){
  721.                 /* Stash in cache and return */
  722.                 Rt_cache.target = tsave;
  723.                 Rt_cache.route = rp;
  724.                 return rp;
  725.             }
  726.         }
  727.         mask <<= 1;
  728.     }
  729.     if(R_default.iface != NULLIF){
  730.         Rt_cache.target = tsave;
  731.         Rt_cache.route = &R_default;
  732.         return &R_default;
  733.     } else
  734.         return NULLROUTE;
  735. }
  736. /* Search routing table for entry with specific width */
  737. struct route *
  738. rt_blookup(target,bits)
  739. int32 target;
  740. unsigned int bits;
  741. {
  742.     register struct route *rp;
  743.   
  744.     if(bits == 0){
  745.         if(R_default.iface != NULLIF)
  746.             return &R_default;
  747.         else
  748.             return NULLROUTE;
  749.     }
  750.     /* Mask off target according to width */
  751.     target &= ~0L << (32-bits);
  752.   
  753.     for(rp = Routes[bits-1][hash_ip(target)];rp != NULLROUTE;rp = rp->next){
  754.         if(rp->target == target){
  755.             return rp;
  756.         }
  757.     }
  758.     return NULLROUTE;
  759. }
  760. /* Scan the routing table. For each entry, see if there's a less-specific
  761.  * one that points to the same interface and gateway. If so, delete
  762.  * the more specific entry, since it is redundant.
  763.  *
  764.  * N7IPB - modified so that entries with target = gateway are correctly merged
  765.  * into entries without a gateway specified.  This allows RIP to work better
  766.  * in situations where you have multiple gateways on the same frequency.
  767.  * Logic is now:
  768.  * if newroute.interface == existingroute.interface and
  769.  *    (newroute.gateway == existingroute.gateway or
  770.  *     newroute.gateway == newroute.targetaddress) then drop the new entry.
  771.  */
  772. void
  773. rt_merge(trace)
  774. int trace;
  775. {
  776.     int bits,i,j;
  777.     struct route *rp,*rpnext,*rp1;
  778.   
  779.     for(bits=32;bits>0;bits--){
  780.         for(i = 0;i<HASHMOD;i++){
  781.             for(rp = Routes[bits-1][i];rp != NULLROUTE;rp = rpnext){
  782.                 rpnext = rp->next;
  783.                 for(j=bits-1;j >= 0;j--){
  784.                     if((rp1 = rt_blookup(rp->target,j)) != NULLROUTE
  785.                         && rp1->iface == rp->iface
  786.                         && (rp1->gateway == rp->gateway
  787.                     || rp->gateway == rp->target)){
  788.                         if(trace > 1)
  789.                             printf("merge %s %d\n",
  790.                             inet_ntoa(rp->target),
  791.                             rp->bits);
  792.                         rt_drop(rp->target,rp->bits);
  793.                         break;
  794.                     }
  795.                 }
  796.             }
  797.         }
  798.     }
  799. }
  800.   
  801. #ifdef IPACCESS
  802. /* check to see if packet is "authorized".  Returns 0 if matching */
  803. /* permit record is found, -1 if not found or deny record found */
  804. int
  805. ip_check(accptr,protocol,src,dest,port)
  806. struct rtaccess *accptr;
  807. int16 protocol,port;
  808. int32 src,dest;
  809. {
  810.     int32 smask,tmask;
  811.   
  812.     for(;accptr != NULLACCESS;accptr = accptr->nxtbits) {
  813.         if ((accptr->protocol == 0) ||
  814.         (accptr->protocol == protocol)) {
  815.             smask = NETBITS(accptr->sbits);
  816.             tmask = NETBITS(accptr->bits);
  817.             if ((accptr->source == (smask & src)) &&
  818.                 (accptr->target == (tmask & dest)) &&
  819.                 ((accptr->lowport == 0) ||
  820.                 ((port >= accptr->lowport) &&
  821.             (port <= accptr->highport)))) {
  822.                 return (accptr->status);
  823.             }
  824.         }
  825.     }
  826.     return -1; /* fall through to here if not found */
  827. }
  828. /* add an entry to the access control list */
  829. /* not a lot of error checking 8-) */
  830. void
  831. addaccess(protocol,source,sbits,target,tbits,ifp,low,high,permit)
  832. int16 protocol;         /* IP protocol */
  833. int32 source,target;        /* Source & target IP address prefix */
  834. unsigned int sbits,tbits;   /* Size of address prefix in bits (0-32) */
  835. struct iface *ifp;      /* Interface to which packet may be routed */
  836. int16 low;
  837. int16 high;
  838. int16 permit;
  839. {
  840.     struct rtaccess *tpacc; /*temporary*/
  841.     struct rtaccess *holder; /*for the new record*/
  842.   
  843.     holder = (struct rtaccess *)callocw(1,sizeof(struct rtaccess));
  844.     holder->nxtiface = NULLACCESS;
  845.     holder->nxtbits = NULLACCESS;
  846.     holder->protocol = protocol;
  847.     holder->source = source;
  848.     holder->sbits = sbits;
  849.     holder->target = target;
  850.     holder->bits = tbits;
  851.     holder->iface = ifp;
  852.     holder->lowport = low;
  853.     holder->highport = high;
  854.     holder->status = permit;
  855.     for(tpacc = IPaccess;tpacc != NULLACCESS;tpacc = tpacc->nxtiface)
  856.         if(tpacc->iface == ifp) { /* get to end */
  857.             while(tpacc->nxtbits != NULLACCESS)
  858.                 tpacc = tpacc->nxtbits;
  859.             tpacc->nxtbits = holder;
  860.             return;
  861.         }
  862.   /* iface wasn't found, so just add at head of list */
  863.     holder->nxtiface = IPaccess;
  864.     IPaccess = holder;
  865. }
  866. #endif
  867.   
  868. #ifdef notdef
  869.   
  870. /* Add an IP datagram to an interface output queue, sorting first by
  871.  * the precedence field in the IP header, and secondarily by an
  872.  * "interactive" flag set by peeking at the transport layer to see
  873.  * if the packet belongs to what appears to be an interactive session.
  874.  * A layer violation, yes, but a useful one...
  875.  */
  876. static int
  877. q_pkt(iface,gateway,ip,bp,ckgood)
  878. struct iface *iface;
  879. int32 gateway;
  880. struct ip *ip;
  881. struct mbuf *bp;
  882. int ckgood;
  883. {
  884.     struct mbuf *tbp,*tlast;
  885.     struct tcp tcp;
  886.     struct qhdr qhdr;
  887.     struct qhdr qtmp;
  888.     int i;
  889.   
  890.     if((tbp = htonip(ip,bp,ckgood)) == NULLBUF){
  891.         free_p(bp);
  892.         return -1;
  893.     }
  894.     bp = pushdown(tbp,sizeof(struct qhdr));
  895.     iface->ipsndcnt++;
  896.     /* create priority field consisting of tos with 2 unused
  897.      * low order bits stripped, one of which we'll use as an
  898.      * "interactive" flag.
  899.      */
  900.     qhdr.tos = (ip->tos & 0xfc);
  901.     qhdr.gateway = gateway;
  902.     if(iface->outq == NULLBUF){
  903.         /* Queue empty, no priority decisions to be made
  904.          * This is the usual case for fast networks like Ethernet,
  905.          * so we can avoid some time-consuming stuff
  906.          */
  907.         memcpy(bp->data,(char *)&qhdr,sizeof(qhdr));
  908.         iface->outq = bp;
  909.     } else {
  910.         /* See if this packet references a "priority" TCP port number */
  911.         if(ip->protocol == TCP_PTCL && ip->offset == 0){
  912.             /* Extract a copy of the TCP header */
  913.             if(dup_p(&tbp,bp,sizeof(struct qhdr)+IPLEN+
  914.             ip->optlen,TCPLEN+TCP_MAXOPT) >= TCPLEN){
  915.                 ntohtcp(&tcp,&tbp);
  916.                 for(i=0;Tcp_interact[i] != -1;i++){
  917.                     if(tcp.source == Tcp_interact[i]
  918.                     || tcp.dest == Tcp_interact[i]){
  919.                         qhdr.tos |= 1;
  920.                         break;
  921.                     }
  922.                 }
  923.             }
  924.             free_p(tbp);
  925.         }
  926.         memcpy(bp->data,(char *)&qhdr,sizeof(qhdr));
  927.         /* Search the queue looking for the first packet with precedence
  928.          * lower than our packet
  929.          */
  930.         tlast = NULLBUF;
  931.         for(tbp = iface->outq;tbp != NULLBUF;tlast=tbp,tbp = tbp->anext){
  932.             memcpy((char *)&qtmp,tbp->data,sizeof(qtmp));
  933.             if(qhdr.tos > qtmp.tos){
  934.                 break;  /* Add it just before tbp */
  935.             }
  936.         }
  937.         bp->anext = tbp;
  938.         if(tlast == NULLBUF){
  939.             /* First on queue */
  940.             iface->outq = bp;
  941.         } else {
  942.             tlast->anext = bp;
  943.         }
  944.     }
  945.     psignal(&iface->outq,1);
  946.     if(iface->outlim != 0 && len_q(iface->outq) >= iface->outlim){
  947.         /* Output queue is at limit; return source quench to
  948.          * the sender of a randomly selected packet on the queue
  949.          */
  950.         rquench(iface,0);
  951.     }
  952.     return 0;
  953. }
  954.   
  955. #endif
  956.   
  957. /* Direct IP input routine for packets without link-level header */
  958. void
  959. ip_proc(iface,bp)
  960. struct iface *iface;
  961. struct mbuf *bp;
  962. {
  963.     ip_route(iface,bp,0);
  964. }
  965.   
  966.   
  967.